/***
 * @Author: zxc
 * @Date: 2020-11-06 09:31:52
 * @LastEditTime: 2020-11-06 10:17:18
 * @LastEditors: zxc
 * @Description:策略模式的定义是:定义一系列的算法，把它们一个个封装起来，并且使它们可以相互替换。
 **/

/**
 * @Author: zxc
 * @Date: 2020-11-09 09:32:12
 * @func 传统面向对象的写法
 */
// let performanceS = function () {}
// performanceS.prototype.calculate = function (salary) {
//   return salary * 4
// }
// let performanceA = function () {}
// performanceA.prototype.calculate = function (salary) {
//   return salary * 3
// }
// let performanceB = function () {}
// performanceB.prototype.calculate = function (salary) {
//   return salary * 2
// }

// let Bonus = function () {
//   this.salary = null
//   this.strategy = null
// }

// // 原始工资
// // 绩效等级对应的策略对象
// Bonus.prototype.setSalary = function (salary) {
//   this.salary = salary // 设置员工的原始工资
// }
// Bonus.prototype.setStrategy = function (strategy) {
//   this.strategy = strategy // 设置员工绩效等级对应的策略对象
// }
// Bonus.prototype.getBonus = function () {
//   // 取得奖金数额
//   return this.strategy.calculate(this.salary) // 把计算奖金的操作委托给对应的策略对象
// }

// let bonus = new Bonus()
// bonus.setSalary(10000)
// bonus.setStrategy(new performanceS()) // 设置策略对象
// console.log(bonus.getBonus()) // 输出:40000
// bonus.setStrategy(new performanceA()) // 设置策略对象
// console.log(bonus.getBonus()) // 输出:30000

//---------------------------------------------

/**
 * @Author: zxc
 * @Date: 2020-11-09 09:36:17
 * @func javascript实现的策略模式
 */
// let strategies = {
//   S(salary) {
//     return salary * 4
//   },
//   A(salary) {
//     return salary * 3
//   },
//   B(salary) {
//     return salary * 2
//   }
// }
// let calculateBonus = function (level, salary) {
//   return strategies[level](salary)
// }
// console.log(calculateBonus("A", 2000))
// console.log(calculateBonus("B", 1000))

//---------------------------------------------------

/**
 * @Author: zxc
 * @Date: 2020-11-09 10:16:37
 * @func 实际使用之表单较验
 */
const startegies = {
  isNoEmpty(value, errMsg) {
    if (value === "") return errMsg
  },
  minLength(value, length, errMsg) {
    if (value.length < length) return errMsg
  },
  maxLength(value, length, errMsg) {
    if (value.length > length) return errMsg
  },
  isMobile(value, errMsg) {
    if (!/(^1[3|5|8][0-9]{9}$)/.test(value)) return errMsg
  }
}

const Validator = function () {
  this.cache = []
}

Validator.prototype.add = function (dom, rule, errMsg) {
  let ary = rule.split(":")
  this.cache.push(function () {
    const strategy = ary.shift()
    ary.unshift(dom)
    ary.push(errMsg)
    return startegies[strategy].apply(dom, ary)
  })
}

Validator.prototype.start = function () {
  let i = 0,
    len = this.cache.length
  for (; i < len; i++) {
    const msg = this.cache[i]()
    if (msg) return msg
  }
}

const validateFunc = function () {
  let validator = new Validator()
  validator.add(registorForm.userName, "isNoEmpty", "用户名不能为空")
  validator.add(registorForm.password, "minLength:6", "密码长度不能小于6位")
  validator.add(registorForm.phoneNumber, "isMobile", "手机号格式错误")
  let errMsg = validator.start()
  return errMsg
}

//模拟的表单
const registorForm = {
  userName: "xc",
  password: "123456",
  phoneNumber: "19923456780",
  onSubmit() {
    const errMsg = validateFunc()
    if (errMsg) {
      alert(errMsg)
      return false
    }
  }
}
registorForm.onSubmit()
